import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository, In } from 'typeorm';
import { ConfigEntity } from '@entity/system/config.entity';
import {
  ListConfigDTO,
  CreateConfigDTO,
  UpdateConfigDTO,
} from '@dto/system/config.dto';
import { resBuild } from '@utils/resBuild';
import { checkKeyIsExist } from '@utils/serviceHelp';
import { getOperator } from '@utils';
import { DownloadExcelService } from '@service/common/downloadExcel';
import { RedisService } from '@midwayjs/redis';
import { RedisEnum } from '@utils/enum';

@Provide()
export class ConfigService {
  @Inject()
  ctx: Context;

  @Inject()
  redisService: RedisService;

  @InjectEntityModel(ConfigEntity)
  configEntity: Repository<ConfigEntity>;

  @Inject()
  protected downloadExcelService: DownloadExcelService;

  // 列表
  async list(queryParams: ListConfigDTO) {
    const queryBuilder = this.configEntity.createQueryBuilder('entity');
    if (queryParams.configName) {
      queryBuilder.andWhere(
        `entity.configName like "%${queryParams.configName}%"`
      );
    }
    if (queryParams.configKey) {
      queryBuilder.andWhere(
        `entity.configKey like "%${queryParams.configKey}%"`
      );
    }
    if (queryParams.configType) {
      queryBuilder.andWhere('entity.configType = :configType', {
        configType: queryParams.configType,
      });
    }

    // 时间范围，包含全天
    if (queryParams['params[beginTime]'] && queryParams['params[endTime]']) {
      queryBuilder.andWhere(
        'entity.createTime BETWEEN :beginTime AND :endTime',
        {
          beginTime: queryParams['params[beginTime]'] + ' 00:00:00',
          endTime: queryParams['params[endTime]'] + ' 23:59:59',
        }
      );
    }

    if (queryParams.pageNum && queryParams.pageSize) {
      queryBuilder
        .skip((queryParams.pageNum - 1) * queryParams.pageSize)
        .take(queryParams.pageSize);
    }

    const [rows, total] = await queryBuilder.getManyAndCount();
    return resBuild.list(rows, total);
  }

  // 添加
  async create(config: CreateConfigDTO) {
    // 新增之前先判断是否已存在
    await checkKeyIsExist(this.configEntity, 'configName', config.configName);
    const myEntity = this.configEntity.create(config);
    myEntity.setCreateBy(getOperator(this.ctx));
    await this.configEntity.save(myEntity);
    // 同时更细redis缓存
    await this.redisService.set(
      `${RedisEnum.SYS_CONFIG_KEY}${config.configKey}`,
      config.configValue
    );
    return resBuild.success();
  }

  // 删除
  async delete(configId: string) {
    const ids = configId.split(',').map(id => Number(id));

    // 同时删除redis缓存
    const delConfigList = await this.configEntity.findBy({
      configId: In(ids),
    });
    for (const item of delConfigList) {
      await this.redisService.del(
        `${RedisEnum.SYS_CONFIG_KEY}${item.configKey}`
      );
    }
    await this.configEntity.delete(ids);
    return resBuild.success();
  }

  // 修改
  async update(config: UpdateConfigDTO) {
    const myEntity = this.configEntity.create(config);
    myEntity.setUpdateBy(getOperator(this.ctx));
    await this.configEntity.save(config);
    // 同时更细redis缓存
    await this.redisService.set(
      `${RedisEnum.SYS_CONFIG_KEY}${config.configKey}`,
      config.configValue
    );
    return resBuild.success();
  }

  // 详情
  async detail(configId: number) {
    const detailInfo = await this.configEntity.findOneBy({
      configId,
    });
    return resBuild.data(detailInfo);
  }

  // 导出
  async export(queryParams: ListConfigDTO) {
    // 默认导出全部，去掉分页参数
    delete queryParams.pageNum;
    delete queryParams.pageSize;
    const headers = [
      { label: '参数主键', prop: 'configId' },
      { label: '参数名称', prop: 'configName' },
      { label: '参数键名', prop: 'configKey' },
      { label: '参数键值', prop: 'configValue' },
      { label: '系统内置', prop: 'configType' },
      { label: '备注', prop: 'remark' },
      { label: '创建时间', prop: 'createTime', width: 25 },
    ];
    const { rows } = await this.list(queryParams);
    return this.downloadExcelService.downloadExcel({
      headers: headers,
      data: rows,
      sheetName: '参数配置',
    });
  }

  // 根据参数键名查询参数值
  async getConfigKey(configKey: string) {
    // 先从redis获取
    const redisValue = await this.redisService.get(
      `${RedisEnum.SYS_CONFIG_KEY}${configKey}`
    );
    if (redisValue) {
      // 如果获取到，直接返回
      return resBuild.success(redisValue);
    } else {
      // 如果未获取到，则从数据库获取，并添加到redis
      const detailInfo = await this.configEntity.findOneBy({
        configKey,
      });
      await this.redisService.set(
        `${RedisEnum.SYS_CONFIG_KEY}${configKey}`,
        detailInfo.configValue
      );
      return resBuild.success(detailInfo.configValue);
    }
  }

  // 刷新缓存
  async refreshCache() {
    const allConfigList = await this.configEntity.find();
    allConfigList.forEach(item => {
      this.redisService.set(
        `${RedisEnum.SYS_CONFIG_KEY}${item.configKey}`,
        item.configValue
      );
    });
    return resBuild.success();
  }
}
